//package hardy.etudejpa.config;
//
//import java.io.Serializable;
//import java.util.ArrayList;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.stream.Collectors;
//
//import org.apache.commons.lang3.NotImplementedException;
//import org.hardy.collection.assemble.CollectionAssemble;
//import org.hardy.collection.assemble.CollectionAssemble.DiffCollection;
//import org.hardy.statics.exception.LogicException;
//import org.hardy.util.chars.NullOREmpty;
//
//import cn.hutool.core.collection.CollUtil;
//
///**
// * -记录分表的信息
// * @author hardy
// *
// */
//public class ShardingRegist {
//	
//	private ShardingRegist() {};
//	
//	private static final ShardingRegist shardingRegist = new ShardingRegist();
//	
//	public static ShardingRegist getInstance() {return shardingRegist;}
//	/**
//	 * -每次调用sql时都会有参数,该参数是当前线程的sql参数
//	 * <br> 在事务控制范围内可能有多个sql的操作，所有操作需要的参数都设置在该对象中
//	 */
//	private ThreadLocal<ThreadParam> threadParam = new ThreadLocal<ThreadParam>();
//	/**
//	 * -记录虚拟表名称和对应的全部实际表名称
//	 */
//	private static Map<String,SubTableInfo> tables = new ConcurrentHashMap<>();
//	/**
//	 * -通过虚拟表名称和分表字段以及对应参数获取要映射表的名称
//	 * @param tableVirtual
//	 * @param ceils
//	 * @return
//	 */
//	public Map<String,List<String>> getMappingTable(String sql){ 
//		 List<String> hasTables = tables.keySet().stream().filter(virtual->sql.indexOf(" "+virtual)>-1).collect(Collectors.toList());
//		 ThreadParam threadParams = threadParam.get();
//		 if(!hasTables.isEmpty()) { //验证一下param
//			for(String virtaul:hasTables) {
//				 if(threadParams==null||threadParams.getEles()==null||threadParams.getEles().isEmpty()) throw new LogicException("virtual table:{} not contains key param:{}",virtaul,tables.get(virtaul).columnNames);
//			}
//		 }else return null;
//		 Map<String,List<String>> result = new HashMap<String, List<String>>();
//		 try {  
//			 for(ThreadParamElement tp:threadParams.getEles().get(threadParams.index++).getEles()) {
//				 if(NullOREmpty.isEmptyString(tp.tableVirtual)) throw new LogicException("ShardingRegist.getMappingTable tableVirtual is null");
//				 if(tp!=null&&tables.containsKey(tp.getTableVirtual())) {
//					 DiffCollection<String> diff = CollectionAssemble.diffrentCollection(tp.params.keySet(), tables.get(tp.tableVirtual).columnNames);
//					 if(diff.getSameElement().size() != tables.get(tp.tableVirtual).columnNames.size()) {
//						 diff.getSecondSelf().removeAll(diff.getSameElement());
//						 throw new LogicException("table:{} column:{} is error",tp.tableVirtual,diff.getSecondSelf());
//					 }
//					 switch (tp.type) {
//					case QUERY:
//						 result.put(tp.tableVirtual, tables.get(tp.tableVirtual).queryAlgorithm.getMappingTable(tables.get(tp.tableVirtual),tp.params));
//						 break;
//					case UPDATE:
//						 result.put(tp.tableVirtual,tables.get(tp.tableVirtual).updateAlgorithm.getMappingTable(tables.get(tp.tableVirtual),tp.params));
//						 break;
//					default:
//						throw new LogicException("ShardingRegist.getMappingTable type is error");
//					}
//				 }
//			 }
//		} catch (Exception e) {
//			e.printStackTrace();
//			throw e;
//		}
//		return result;
//	}
//	
//	public void cleanThreadParam() {
//		threadParam.set(null);
//	}
//	 
//	/**
//	 * -设置分表的信息
//	 * @param tableVirtual
//	 * @param info
//	 */
//	public static void addTableInfo(String tableVirtual,SubTableInfo info) {
//		 if(NullOREmpty.isEmptyString(info.tableVirtual))info.tableVirtual = tableVirtual;
//		 if(NullOREmpty.isEmptyString(tableVirtual)||!info.tableVirtual.equals(tableVirtual)) throw new LogicException("tableVirtual is error:{},{}",tableVirtual,info.tableVirtual) ;
//		 tables.put(tableVirtual, info);
//	}
//	/**  
//	 * -在数据库搜索中插入线程参数
//	 * @param params
//	 * @return
//	 */
//	public ShardingRegist addNextThreadParam(String callMethodName,List<ThreadParamElement> params) {
//		if(threadParam.get()==null) {
//			threadParam.set(new ThreadParam());
//		}
//		threadParam.get().addNextEles(callMethodName,params);
//		return this;
//	}
//	/** 
//	 * -在数据库搜索中插入线程参数
//	 * @param params
//	 * @return
//	 */
//	public ShardingRegist addNextThreadParam(String callMethodName,ThreadParamElement params) {
//		if(threadParam.get()==null) {
//			threadParam.set(new ThreadParam());
//		}
//		threadParam.get().addNextEles(callMethodName,params);
//		return this;
//	}
//	/**
//	 * -获取当前最后一个thread参数的方法名称
//	 * @return
//	 */
////	public String getLastMethodName() {
////		
////	}
//	/**
//	 * -分表策略
//	 * @author hardy
//	 *
//	 */
//	public static interface TableCielAlgorithm{
//		/**
//		 * -根据条件获取要分表的名称
//		 * @param info
//		 * @param params
//		 * @return
//		 */
//		List<String> getMappingTable(SubTableInfo info,Map<String,Comparable<?>> params);
//	} 
//	/**
//	 * -表示一个虚拟表对应的分表和他的对应分表信息
//	 * <br> key是分表名称,value是分表的数据库列名称和对应的关键值
//	 * @author hardy
//	 *
//	 */
//	public static class SubTableInfo extends ArrayList<String>{
//		private static final long serialVersionUID = 1L;
//		
//		private String tableVirtual;
//		/**
//		 * -分表的列名称
//		 */
//		private List<String> columnNames = new ArrayList<>();
//		
//		/**
//		 * -设置虚拟表名称
//		 * @param tableVirtual
//		 * @return
//		 */
//		public SubTableInfo setTableVirtual(String tableVirtual) {
//			this.tableVirtual = tableVirtual;
//			return this;
//		}
//		/**
//		 * -获取关联的虚拟表
//		 * @return
//		 */
//		public String getTableVirtual() {
//			return tableVirtual;
//		}
//		/**
//		 * -insert,update,delete的分表策略
//		 */
//		private TableCielAlgorithm updateAlgorithm = new TableCielAlgorithm() {
//			
//			@Override
//			public List<String> getMappingTable(SubTableInfo info, Map<String, Comparable<?>> params) {
//				throw new NotImplementedException("not implement SubTableInfo.getMappingTable");
//			}
//		};
//		/**
//		 * -查询时的分表策略
//		 */
//		private TableCielAlgorithm queryAlgorithm = new TableCielAlgorithm() {
//			
//			@Override
//			public List<String> getMappingTable(SubTableInfo info, Map<String, Comparable<?>> params) {
//				throw new NotImplementedException("not implement SubTableInfo.getMappingTable");
//			}
//		};
//		/**
//		 * -设置分表策略
//		 * @param algorithm
//		 * @return
//		 */
//		public SubTableInfo setAlgorithm(Type type,TableCielAlgorithm algorithm) {
//			switch (type) {
//			case QUERY:
//				this.queryAlgorithm = algorithm;
//				break;
//			case UPDATE:
//				this.updateAlgorithm = algorithm;
//				break;
//			default:
//				break;
//			}
//			return this;
//		}
//		/**
//		 * -设置分表策略
//		 * @param algorithm
//		 * @return
//		 */
//		public SubTableInfo setAlgorithm(TableCielAlgorithm algorithm) {
//			this.queryAlgorithm = algorithm;
//			this.updateAlgorithm = algorithm;
//			return this;
//		}
//		/**
//		 * -添加分表的关键字段，和字段对应的值
//		 * @param subTable
//		 * @return
//		 */
//		public SubTableInfo addSubTable(String subTable) {
//			if(!this.contains(subTable))this.add(subTable);
//			return this;
//		}
//		/**
//		 * -添加关键的分表字段 
//		 * @param columnNames
//		 * @return
//		 */
//		public SubTableInfo addColumnName(String... columnNames) {
//			for(String columnName:columnNames) {
//				 if(!this.columnNames.contains(columnName))this.columnNames.add(columnName);
//			}
//			return this;
//		}
//		
//		/**
//		 * -构建SubTableInfo
//		 * @param tableVirtual
//		 * @return
//		 */
//		public static SubTableInfo build(String... columnNames) {
//			SubTableInfo info = new SubTableInfo();
//			 for(String column:columnNames) {
//				 if(!info.columnNames.contains(column))info.columnNames.add(column);
//			 }
//			 return info;
//		}
//		 
//	}
//	
//	public static class CeilKey implements Serializable{
//		private static final long serialVersionUID = 1L;
//		private String columnName;
//		public String getColumnName() {
//			return columnName;
//		}
//		public CeilKey setColumnName(String columnName) {
//			this.columnName = columnName;
//			return this;
//		}
//		
//		public static CeilKey build(String columnName) {
//			return new CeilKey().setColumnName(columnName); 
//		}
//	}
//	
//	 public static enum Type{
//		 UPDATE,QUERY
//	 }
//	 /**
//	  * -表示一个线程上的传输的sql信息
//	  * @author hardy
//	  *
//	  */
//	 public static class ThreadParamElement{
//		 private String tableVirtual;
//		 private Type type;
//		 private Map<String,Comparable<?>> params = new HashMap<String, Comparable<?>>();
//		 
//		 public ThreadParamElement setType(Type type) {
//			 this.type = type;
//			 return this;
//		 }
//		 
//		 public Type getType() {
//			 return this.type;
//		 }
//		 public String getTableVirtual() {
//			return tableVirtual;
//		}
//		/**
//		 * -设置虚拟表名称
//		 * @param tableVirtual
//		 * @return
//		 */
//		public ThreadParamElement setTableVirtual(String tableVirtual) {
//			this.tableVirtual = tableVirtual;
//			return this;
//		}
//		public Map<String, Comparable<?>> getParams() {
//			return params;
//		}
//		/**
//		 * -添加分表条件
//		 * @param params
//		 * @return
//		 */
//		public ThreadParamElement setParams(Map<String, Comparable<?>> params) {
//			this.params = params;
//			return this;
//		}
//		 /**
//		  * -添加一个分表条件
//		  * @param columnName
//		  * @param param
//		  * @return
//		  */
//		 public ThreadParamElement addParam(String columnName,Comparable<?> param) {
//			 this.params.put(columnName, param);
//			 return this;
//		 }
//		 /**
//		  * -构造ThreadParam对象
//		  * @param virtualTable
//		  * @param type
//		  * @return
//		  */
//		 public static ThreadParamElement build(String virtualTable,Type type) {
//			 return new ThreadParamElement().setTableVirtual(virtualTable).setType(type);
//		 }
//	 }
//	 /**
//	  * -整体的事务控制范围内的全部线程参数
//	  * @author hardy
//	  *
//	  */
//	 public static class ThreadParam{
//		 /**
//		  * -对于事务内多个sql操作，每一个sql操作对饮eles中的一条List数据
//		  */
//		 private List<ThreadParamEles> eles = new ArrayList<ThreadParamEles>();
//		 private int index = 0;
//		 
//		public List<ThreadParamEles> getEles() {
//			return eles;
//		}
//		/**
//		 * -设置整体条件
//		 * @param eles
//		 */
//		public void setEles(List<ThreadParamEles> eles) {
//			this.eles = eles;
//		}
//		/**
//		 * -添加一个新的参数条件
//		 * <br> 该条件应用于新的数据库处理中
//		 * @param callMethodName  调用的方法名称
//		 * @param eles
//		 * @return
//		 */
//		public ThreadParam addNextEles(String callMethodName,List<ThreadParamElement> eles) {
//			ThreadParamEles teles = new ThreadParamEles();
//			teles.setCallMethodName(callMethodName);
//			teles.setEles(eles);
//			this.eles.add(teles); 
//			return this;
//		}
//		/**
//		 * -添加一个新的参数条件
//		 * <br> 该条件应用于新的数据库处理中
//		 * @param callMethodName
//		 * @param ele
//		 * @return
//		 */
//		public ThreadParam addNextEles(String callMethodName,ThreadParamElement ele) {
//			ThreadParamEles teles = new ThreadParamEles();
//			teles.setCallMethodName(callMethodName);
//			teles.setEles(CollUtil.newArrayList(ele));
//			this.eles.add(teles);
//			return this;
//		}
//		/**
//		 * -在当前数据库操作中添加参数条件
//		 * @param callMethodName
//		 * @param eles
//		 * @return
//		 */
//		public ThreadParam addCurrentEles(String callMethodName,List<ThreadParamElement> eles) {
//			if(this.eles.isEmpty()) this.addNextEles(callMethodName, eles);
//			else this.eles.get(this.eles.size()-1).getEles().addAll(eles);
//			return this;
//		}
//		/**
//		 *  -在当前数据库操作中添加参数条件
//		 * @param callMethodName
//		 * @param ele
//		 * @return
//		 */
//		public ThreadParam addCurrentEles(String callMethodName,ThreadParamElement ele) {
//			if(this.eles.isEmpty()) this.addNextEles(callMethodName, CollUtil.newArrayList(ele));
//			else this.eles.get(this.eles.size()-1).getEles().add(ele);
//			return this;
//		}
//		 
//		public int getIndex() {
//			return index;
//		}
//		public void setIndex(int index) {
//			this.index = index;
//		}
//		 
//		public void indexPlus() {
//			this.index++;
//		}
//		 
//	 }
//	 
//	 public static class ThreadParamEles{
//		 private String callMethodName;
//		 private List<ThreadParamElement> eles = new ArrayList<ShardingRegist.ThreadParamElement>();
//		public String getCallMethodName() {
//			return callMethodName;
//		}
//		public void setCallMethodName(String callMethodName) {
//			this.callMethodName = callMethodName;
//		}
//		public List<ThreadParamElement> getEles() {
//			return eles;
//		}
//		public void setEles(List<ThreadParamElement> eles) {
//			this.eles = eles;
//		}
//		 
//	 }
//}
